package com.matt.service.impl;

import com.matt.domain.Children;
import com.matt.domain.ChildrenHealthBaseInfo;
import com.matt.domain.Feeds;
import com.matt.foundation.constant.FeedsConstant;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.foundation.query.ChildrenQuery;
import com.matt.foundation.query.HealthQuery;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.annotation.OptsTrace;
import com.tuo51.foudation.utils.export.HealthReportUtil;
import com.matt.foundation.vo.ChildChildrenHealthListVo;
import com.matt.foundation.vo.ChildrenHealthListVo;
import com.matt.repository.ChildrenHealthBaseInfoRepository;
import com.matt.repository.ChildrenRepository;
import com.matt.repository.base.ChildChildrenExtendRepository;
import com.matt.service.*;
import com.matt.service.remoteCall.SsoCallService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2017/11/1
 * *******************************
 */
@Service
@Slf4j
public class ChildrenHealthServiceImpl implements ChildrenHealthService {
    @Autowired
    private ChildrenService childrenService;

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private ChildrenHealthBaseInfoRepository childrenHealthBaseInfoRepository;

    @Autowired
    private ChildChildrenExtendRepository childChildrenExtendRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private WxPushService wxPushService;

    @Autowired
    private FeedsService feedsService;


    @Override
    public Page<ChildChildrenHealthListVo> getChildChildrenHealthPage(ChildrenQuery childrenQuery) {

        Integer pageNum = childrenQuery.getPageNum();
        Integer pageSize = childrenQuery.getPageSize();
        int num = pageNum+1;
        if (pageNum == null || pageNum < 0) {
            pageNum = 0;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        Integer pageNum1 = (num - 1) * pageSize;
//        Integer pageNum1 =  pageSize;
        Integer pageSize1 = num * pageSize;

        childrenQuery.setPageNum(pageNum1);
        List<Children> childrenList = childChildrenExtendRepository.findChildrenByCondition(childrenQuery);
        Long count = childChildrenExtendRepository.countChildrenByCondition(childrenQuery);
        List<ChildChildrenHealthListVo> list = Lists.newArrayList();
        childrenList.forEach(o -> {
            List<ChildrenHealthBaseInfo> baseInfoList = childrenHealthBaseInfoRepository.findByChildrenIdOrderByCreatedDesc(o.getId());
            list.add(ChildChildrenHealthListVo.of(o, baseInfoList));
        });
        return new PageImpl<ChildChildrenHealthListVo>(list, PageRequest.of(pageNum, pageSize), count);
    }

    @Override
    public Page<ChildrenHealthListVo> getChildrenHealthPage(HealthQuery healthQuery) {


        Specification<ChildrenHealthBaseInfo> specification = new Specification<ChildrenHealthBaseInfo>() {
            @Override
            public Predicate toPredicate(Root<ChildrenHealthBaseInfo> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();

                if (StringUtils.isNotBlank(healthQuery.getChildrenId()))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("childrenId"), healthQuery.getChildrenId())));

                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("created")));
                return query.getRestriction();
            }
        };
        Pageable pageable = PageRequest.of(healthQuery.getPageNum(), healthQuery.getPageSize());
        Page<ChildrenHealthBaseInfo> page = childrenHealthBaseInfoRepository.findAll(specification, pageable);

        Children children = childrenService.getById(healthQuery.getChildrenId());
        List<ChildrenHealthListVo> list = page.getContent().stream().map(o -> ChildrenHealthListVo.of(children, o)).collect(Collectors.toList());
        return new PageImpl<ChildrenHealthListVo>(list, pageable, page.getTotalElements());
    }

    @Override
    public Map findHealthInfoDetail(StaffDTO staff, String id) {
        Map map = new HashMap();
        ChildrenHealthBaseInfo healthBaseInfo = childrenHealthBaseInfoRepository.getOne(id);
        Children children = childrenService.getById(healthBaseInfo.getChildrenId());

        map.put("children", children);
        map.put("healthBaseInfo", healthBaseInfo);
        map.put("teacher", staff.getRealName());

       // wxPushService.pushChildrenHealthRecord(healthBaseInfo);//测试后删除
        return map;
    }


    @Transactional
    @OptsTrace(code = "0307")
    @Override
    public void addHealthInfo(ChildrenHealthBaseInfo childrenHealthBaseInfo, String childrenId, String height, String weight) {
        Children children = childrenService.getById(childrenId);
        changeChildren(children, height, weight);

        childrenHealthBaseInfo.setChildrenId(childrenId);
        childrenHealthBaseInfo.setMonth(DateUtil.betweenMonths(new Date(), children.getBirthday()));

        // 计算 身高体重的 年龄分数
        String gender = (children.getGender() == 0)?"girl":"boy";
        if(StringUtils.isNotEmpty(childrenHealthBaseInfo.getPhysicalHeight())) {
            double h = Double.parseDouble(childrenHealthBaseInfo.getPhysicalHeight());
            String hresult = HealthReportUtil.calcHeightPercent(childrenHealthBaseInfo.getMonth(), gender, h);
            childrenHealthBaseInfo.setGrowEvaluateHeightScale(HealthReportUtil.readablePercent(hresult));
        }

        if(StringUtils.isNotEmpty(childrenHealthBaseInfo.getPhysicalWeight())) {
            double w = Double.parseDouble(childrenHealthBaseInfo.getPhysicalWeight());
            String wresult = HealthReportUtil.calcWeightPercent(childrenHealthBaseInfo.getMonth(), gender, w);
            childrenHealthBaseInfo.setGrowEvaluateWeightScale(HealthReportUtil.readablePercent(wresult));
        }

        childrenHealthBaseInfoRepository.save(childrenHealthBaseInfo);
        List<ChildrenHealthBaseInfo>  recordList = childrenHealthBaseInfoRepository.findByChildrenIdOrderByCreatedDesc(childrenId);
        ChildrenHealthBaseInfo record = recordList.get(0);

        //时光轴
        Feeds feeds = feedsService.save(record.getTeacherId(), record.getChildrenId(), children.getAreaId(), "", FeedsConstant.EVALUATE_RECORD_HEALTH, String.format("%s的儿保评测报告", children.getName()), "", "", "", record.getId());

        //推送儿保评测到微信
        wxPushService.pushChildrenHealthRecord(record,null);
    }

    private void changeChildren(Children children, String height, String weight) {
        if (StringUtils.isBlank(children.getHeight()) || StringUtils.isBlank(children.getWeight())) {
            if (StringUtils.isBlank(children.getHeight()))
                children.setHeight(height);
            if (StringUtils.isBlank(children.getWeight()))
                children.setWeight(weight);
            childrenRepository.save(children);
        }
    }

    @Transactional
    @OptsTrace(code = "0308")
    @Override
    public void modifyHealthInfo(ChildrenHealthBaseInfo info, String height, String weight) {
        ChildrenHealthBaseInfo baseInfo = childrenHealthBaseInfoRepository.getOne(info.getId());
        Children children = childrenService.getById(baseInfo.getChildrenId());
        changeChildren(children, height, weight);

        baseInfo.setMonth(DateUtil.betweenMonths(new Date(), children.getBirthday()));
        baseInfo.setGestationalAge(info.getGestationalAge());
        baseInfo.setDeliveryWay(info.getDeliveryWay());
        baseInfo.setComplexion(info.getComplexion());
        baseInfo.setSpirit(info.getSpirit());
        baseInfo.setReaction(info.getReaction());
        baseInfo.setTemperature(info.getTemperature());
        baseInfo.setPulse(info.getPulse());
        baseInfo.setBreathe(info.getBreathe());
        baseInfo.setSkull(info.getSkull());
        baseInfo.setHair(info.getHair());
        baseInfo.setEyelid(info.getEyelid());
        baseInfo.setConjunctiva(info.getConjunctiva());
        baseInfo.setNose(info.getNose());
        baseInfo.setOralCavity(info.getOralCavity());
        baseInfo.setChestShape(info.getChestShape());
        baseInfo.setHeart(info.getHeart());
        baseInfo.setLung(info.getLung());
        baseInfo.setAbdomenShape(info.getAbdomenShape());
        baseInfo.setUmbilicalRegion(info.getUmbilicalRegion());
        baseInfo.setLiver(info.getLiver());
        baseInfo.setSpleen(info.getSpleen());
        baseInfo.setMasses(info.getMasses());
        baseInfo.setGenitals(info.getGenitals());
        baseInfo.setAnus(info.getAnus());
        baseInfo.setSpine(info.getSpine());
        baseInfo.setLimbs(info.getLimbs());
        baseInfo.setIcterus(info.getIcterus());
        baseInfo.setRash(info.getRash());
        baseInfo.setMoroReflex(info.getMoroReflex());
        baseInfo.setGraspReflex(info.getGraspReflex());
        baseInfo.setCrawlingReflex(info.getCrawlingReflex());
        baseInfo.setSteppingReflex(info.getSteppingReflex());
        baseInfo.setNervousSystemOther(info.getNervousSystemOther());
        baseInfo.setPhysicalHeight(info.getPhysicalHeight());
        baseInfo.setPhysicalWeight(info.getPhysicalWeight());
        baseInfo.setPhysicalHeader(info.getPhysicalHeader());
        baseInfo.setPhysicalCircumference(info.getPhysicalCircumference());
        baseInfo.setPhysicalBregma(info.getPhysicalBregma());
        baseInfo.setGrowEvaluateHeightScale(info.getGrowEvaluateHeightScale());
        baseInfo.setGrowEvaluateWeightScale(info.getGrowEvaluateWeightScale());
        baseInfo.setPreviousHistorySick(info.getPreviousHistorySick());
        baseInfo.setFamilyHistoryAllergicDisease(info.getFamilyHistoryAllergicDisease());
        baseInfo.setFamilyHistoryHereditaryDisease(info.getFamilyHistoryHereditaryDisease());
        baseInfo.setFeedHistoryFeedingPatterns(info.getFeedHistoryFeedingPatterns());
        baseInfo.setFeedHistoryFeedingTimes(info.getFeedHistoryFeedingTimes());
        baseInfo.setFeedHistoryFeedingQuantity(info.getFeedHistoryFeedingQuantity());
        baseInfo.setFeedHistoryComplementaryBetween(info.getFeedHistoryComplementaryBetween());
        baseInfo.setFeedHistoryComplementaryCategory(info.getFeedHistoryComplementaryCategory());
        baseInfo.setFeedHistoryComplementaryQuantity(info.getFeedHistoryComplementaryQuantity());
        baseInfo.setFeedHistoryComplementaryHereditary(info.getFeedHistoryComplementaryHereditary());
        baseInfo.setRoutineWakeUpTime(info.getRoutineWakeUpTime());
        baseInfo.setRoutineSleepInertia(info.getRoutineSleepInertia());
        baseInfo.setRoutineSleepTime(info.getRoutineSleepTime());
        baseInfo.setRoutineBathFrequency(info.getRoutineBathFrequency());
        baseInfo.setRoutineBathTime(info.getRoutineBathTime());
        baseInfo.setRoutineDefecationFrequency(info.getRoutineDefecationFrequency());
        baseInfo.setRoutineDefecationCharacter(info.getRoutineDefecationCharacter());
        baseInfo.setRoutineOutFrequency(info.getRoutineOutFrequency());
        baseInfo.setRoutineOutTime(info.getRoutineOutTime());
        baseInfo.setParentsAttentionQuestion1(info.getParentsAttentionQuestion1());
        baseInfo.setParentsAttentionQuestion2(info.getParentsAttentionQuestion2());
        baseInfo.setHealthGuide1(info.getHealthGuide1());
        baseInfo.setHealthGuide2(info.getHealthGuide2());
        baseInfo.setHealthGuide3(info.getHealthGuide3());
        baseInfo.setHealthGuide4(info.getHealthGuide4());
        baseInfo.setEvaluateName(info.getEvaluateName());
        childrenHealthBaseInfoRepository.save(baseInfo);
    }

    @Override
    public ChildrenHealthBaseInfo findById(String id) {
        return childrenHealthBaseInfoRepository.getOne(id);
    }
}
